package ro.ubbcluj.cs.validation.framework.model;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;

import ro.ubbcluj.cs.validation.framework.core.ParameterName;
import ro.ubbcluj.cs.validation.framework.core.ValidationError;
import ro.ubbcluj.cs.validation.framework.core.ValidationErrorType;

public class NumberValidator extends BaseValidator {

	private String[] paramValue;
	private Map<ParameterName, String> validationParameters;
	
	public NumberValidator(String[] paramValue, Map<ParameterName, String> validationParameters) {
		this.paramValue = paramValue;
		this.validationParameters = validationParameters;
	}
	
	private ValidationError validateNumber(String value, Map<ParameterName, String> validationParameters){
		if (StringUtils.isNotEmpty(value)) {
			String numberformat = validationParameters.get(ParameterName.numberformat);
			if (numberformat == null || numberformat.equalsIgnoreCase("int")){
				try {
					Integer.parseInt(value);
				} catch (Exception e) {
					return new ValidationError(ValidationErrorType.NOT_INT_NUMBER, null);
				}
			} else {
				try {
					Double.parseDouble(value);
				} catch (Exception e) {
					return new ValidationError(ValidationErrorType.NOT_REAL_NUMBER, null);
				}
			}			
		}
		return ValidationError.NO_ERRORS;
	}
	
	private ValidationError validateMinValue(String value, Map<ParameterName, String> validationParameters){
		String minvalue = validationParameters.get(ParameterName.minvalue);
		if (StringUtils.isNotEmpty(value) && minvalue != null && Double.parseDouble(value) < Double.parseDouble(minvalue)) {
			return new ValidationError(ValidationErrorType.MIN_VALUE, new String[]{minvalue});
		}
		return ValidationError.NO_ERRORS;
	}
	
	private ValidationError validateMaxValue(String value, Map<ParameterName, String> validationParameters){
		String maxvalue = validationParameters.get(ParameterName.maxvalue);
		if (StringUtils.isNotEmpty(value) && maxvalue != null && Double.parseDouble(value) > Double.parseDouble(maxvalue)) {
			return new ValidationError(ValidationErrorType.MAX_VALUE, new String[]{maxvalue});
		}
		return ValidationError.NO_ERRORS;
	}
	
	public List<ValidationError> validate() {
		List<ValidationError> errors = new ArrayList<ValidationError>();
		for(String value : paramValue){
			ValidationError requiredCheck = validateRequired(value, validationParameters);
			if (requiredCheck != ValidationError.NO_ERRORS) {
				errors.add(requiredCheck);
			} else {
				ValidationError numberCheck = validateNumber(value, validationParameters);
				if (numberCheck != ValidationError.NO_ERRORS) {
					errors.add(numberCheck);
				} else {
					ValidationError minLenCheck = validateMinLength(value, validationParameters);
					ValidationError maxLenCheck = validateMaxLength(value, validationParameters);
					ValidationError minValueCheck = validateMinValue(value, validationParameters);
					ValidationError maxValueCheck = validateMaxValue(value, validationParameters);			
					if (minLenCheck != ValidationError.NO_ERRORS) {
						errors.add(minLenCheck);
					}
					if (maxLenCheck != ValidationError.NO_ERRORS) {
						errors.add(maxLenCheck);
					}
					if (minValueCheck != ValidationError.NO_ERRORS) {
						errors.add(minValueCheck);
					}
					if (maxValueCheck != ValidationError.NO_ERRORS) {
						errors.add(maxValueCheck);
					}
				}
			}
		}		
		return errors;
	}

	public final String[] getParamValue() {
		return paramValue;
	}

	public final void setParamValue(String[] paramValue) {
		this.paramValue = paramValue;
	}

	public final Map<ParameterName, String> getValidationParameters() {
		return validationParameters;
	}

	public final void setValidationParameters(Map<ParameterName, String> validationParameters) {
		this.validationParameters = validationParameters;
	}
}
